#define __STDC_CONSTANT_MACROS
#ifndef MYOBJECT_H
#define MYOBJECT_H
#include <winsock2.h>
#include <windows.h>
#include <winldap.h>
#include <ntldap.h>
#include <stdio.h>
#include <rpcdce.h>
#include <wchar.h>
#include <uv.h>
#include <napi.h>
#include <chrono>
#include <iostream>
#include <string>
#include <thread>
#include <vector>
#include <set>
#include <map>
#include <algorithm>
#include <iterator>
#include <atlconv.h>
#include <wmistr.h>
#include <comutil.h>

using namespace Napi;
using namespace std;


struct AsyncArgs
{
  ULONG msgId;
  __int64 iUSNChanged;
  PWCHAR dn;
  uv_async_t handle;
  Napi::Function *callback;
};

typedef struct ThreadData
{
  string status;
  vector<string> addGUIDs;
  vector<string> delGUIDs;
  // [{ "object": "111", "cn": aaa }, {}]
  vector<map<string, string>> addObject;
  vector<map<string, string>> delObject;
} LINETYPE;

struct ParamsStrut
{
  LDAP *pldapConnection;
  vector<string> pGUIDs;
  vector<string> nGUIDs;
  Napi::Object _ldapConfig;
};
// #define _CRT_SECURE_NO_WARNINGS

wchar_t* Str2Wchar_t(const string &str);
string Wcahr_t2Str(const wchar_t* &pwc);


void CheckAddOrDelObj(const Napi::CallbackInfo *info, ParamsStrut *paramsStrut);
VOID BuildGUIDString(WCHAR *szGUID, LPBYTE pGUID);

class ADObserver : public Napi::ObjectWrap<ADObserver>
{
public:
  static Napi::Object Init(Napi::Env env, Napi::Object exports);
  static Napi::Object NewInstance(Napi::Env env, Napi::Value arg);
  double Val() const { return counter_; };
  ADObserver(const Napi::CallbackInfo &info);
  Napi::Value Value(const Napi::CallbackInfo &info);

private:
  Napi::Value PlusOne(const Napi::CallbackInfo &info);
  Napi::Value PlusTwo(const Napi::CallbackInfo &info);
  double counter_;

  Napi::Object _ldapConfig;
  LDAP *pldapConnection;
  LDAPControl simpleControl;     //  Structure used to represent both client and server controls.
  BOOL bSuccess = FALSE;         //  Results from processing search results.
  ULONG version = LDAP_VERSION3; //  LDAP version 3.
  INT inumberOfChanges = 300;    //  The number of changes to monitor.
  PLDAPControl controlArray[2];  //  Pointer to the LDAPControl.
  LONG msgId;                    //  Used to identify the message.
  LDAPMessage *presults = NULL;  //  Pointer to LDAPMessage data structure used to contain the search results.
  LDAPMessage *pmessage = NULL;  //  Pointer to an LDAPMessage data structure used to contain each entry of the search results.
  __int64 iUSNChanged = 0;       //  Stores the latest USNChanged value for the object.
  vector<LPWSTR> szAttribs;
  LDAPMessage *nextresults = NULL;
  vector<string> pGUIDs;
  vector<string> nGUIDs;
  //  AddObj;
  Napi::Value
  Open(const Napi::CallbackInfo &info);
  Napi::Value Bind(const Napi::CallbackInfo &info);
  Napi::Value StartMonitor(const Napi::CallbackInfo &info);
  Napi::Value StopMonitor(const Napi::CallbackInfo &info);
  Napi::Value Unbind(const Napi::CallbackInfo &info);
  Napi::Value Change(const Napi::CallbackInfo &info);

  BOOL ProcessResult(LDAP *pldapConnection, LDAPMessage *pmessage, __int64 *piUSNChanged, Napi::Object *messageObj);
  void ValidateParams(Napi::Object *initObj);
};

#endif